电商网站开发教程

1. React 简介和特性

1.1 React 是什么?

React 是一个用于构建用户界面的 JavaScript 库。它由 Facebook 开发并维护,广泛用于构建单页应用(SPA)和复杂的用户界面。

1.2 React 的主要特性

  • 组件化:React 将 UI 拆分为独立的、可重用的组件。
  • 虚拟 DOM:React 使用虚拟 DOM 来优化性能,减少直接操作真实 DOM 的次数。
  • 单向数据流:数据在组件树中只能从父组件流向子组件。

2. 环境搭建

2.1 安装 Node.js 和 npm

首先,你需要安装 Node.js 和 npm(Node 包管理器)。你可以从 Node.js 官网 下载并安装。

2.2 使用 Create React App

Create React App 是一个官方推荐的工具链,用于快速搭建 React 项目。

npx create-react-app my-ecommerce-app
cd my-ecommerce-app
npm start

3. JSX 语法

3.1 什么是 JSX?

JSX 是一种 JavaScript 的语法扩展,允许你在 JavaScript 中编写类似 HTML 的代码。

const element = <h1>Hello, world!</h1>;

3.2 JSX 的优点

  • 可读性高:JSX 使代码更接近 HTML,易于理解和维护。
  • 灵活性:可以在 JSX 中嵌入 JavaScript 表达式。

4. 组件基础

4.1 函数组件

函数组件是一个简单的 JavaScript 函数,返回 JSX。

function Welcome(props) {
  return <h1>Hello, {props.name}</h1>;
}

4.2 类组件

类组件是使用 ES6 类定义的组件。

class Welcome extends React.Component {
  render() {
    return <h1>Hello, {this.props.name}</h1>;
  }
}

5. Props 和 State

5.1 Props

Props 是组件的输入参数,用于从父组件向子组件传递数据。

function Welcome(props) {
  return <h1>Hello, {props.name}</h1>;
}

5.2 State

State 是组件内部的状态,用于管理组件的动态数据。

class Clock extends React.Component {
  constructor(props) {
    super(props);
    this.state = { date: new Date() };
  }

  render() {
    return (
      <div>
        <h1>Hello, world!</h1>
        <h2>It is {this.state.date.toLocaleTimeString()}.</h2>
      </div>
    );
  }
}

6. 生命周期方法

6.1 常用生命周期方法

  • componentDidMount:组件挂载后调用。
  • componentDidUpdate:组件更新后调用。
  • componentWillUnmount:组件卸载前调用。
class Clock extends React.Component {
  componentDidMount() {
    this.timerID = setInterval(() => this.tick(), 1000);
  }

  componentWillUnmount() {
    clearInterval(this.timerID);
  }

  tick() {
    this.setState({
      date: new Date()
    });
  }

  render() {
    return (
      <div>
        <h1>Hello, world!</h1>
        <h2>It is {this.state.date.toLocaleTimeString()}.</h2>
      </div>
    );
  }
}

7. 事件处理

7.1 事件绑定

在 React 中,事件处理函数可以通过 onClick 等属性绑定。

function ActionButton() {
  function handleClick() {
    alert('Button clicked!');
  }

  return (
    <button onClick={handleClick}>
      Click me
    </button>
  );
}

8. 条件渲染

8.1 使用条件运算符

你可以使用 JavaScript 的条件运算符来实现条件渲染。

function Greeting(props) {
  const isLoggedIn = props.isLoggedIn;
  return (
    <div>
      {isLoggedIn ? <h1>Welcome back!</h1> : <h1>Please sign up.</h1>}
    </div>
  );
}

9. 列表和 Keys

9.1 渲染列表

你可以使用 map 函数来渲染列表。

const numbers = [1, 2, 3, 4, 5];
const listItems = numbers.map((number) =>
  <li key={number.toString()}>
    {number}
  </li>
);

9.2 Keys

Keys 帮助 React 识别哪些元素改变了,添加了,或者删除了。

const numbers = [1, 2, 3, 4, 5];
const listItems = numbers.map((number) =>
  <li key={number.toString()}>
    {number}
  </li>
);

10. 表单处理

10.1 受控组件

受控组件是指其值由 React 控制的表单元素。

class NameForm extends React.Component {
  constructor(props) {
    super(props);
    this.state = { value: '' };
  }

  handleChange = (event) => {
    this.setState({ value: event.target.value });
  }

  handleSubmit = (event) => {
    alert('A name was submitted: ' + this.state.value);
    event.preventDefault();
  }

  render() {
    return (
      <form onSubmit={this.handleSubmit}>
        <label>
          Name:
          <input type="text" value={this.state.value} onChange={this.handleChange} />
        </label>
        <input type="submit" value="Submit" />
      </form>
    );
  }
}

11. 组合 vs 继承

11.1 组合

React 推荐使用组合而非继承来实现代码复用。

function Dialog(props) {
  return (
    <FancyBorder color="blue">
      <h1 className="Dialog-title">
        {props.title}
      </h1>
      <p className="Dialog-message">
        {props.message}
      </p>
    </FancyBorder>
  );
}

12. 高阶组件 (HOC)

12.1 什么是 HOC?

高阶组件是一个函数,接收一个组件并返回一个新的组件。

function withSubscription(WrappedComponent, selectData) {
  return class extends React.Component {
    constructor(props) {
      super(props);
      this.state = {
        data: selectData(DataSource, props)
      };
    }

    render() {
      return <WrappedComponent data={this.state.data} {...this.props} />;
    }
  };
}

13. Render Props

13.1 什么是 Render Props?

Render Props 是一种通过函数 prop 来共享代码的技术。

class MouseTracker extends React.Component {
  render() {
    return (
      <div>
        <h1>Move the mouse around!</h1>
        <Mouse render={mouse => (
          <Cat mouse={mouse} />
        )}/>
      </div>
    );
  }
}

14. Context API

14.1 什么是 Context API?

Context API 提供了一种在组件树中共享数据的方式,无需手动通过 props 传递。

const ThemeContext = React.createContext('light');

class App extends React.Component {
  render() {
    return (
      <ThemeContext.Provider value="dark">
        <Toolbar />
      </ThemeContext.Provider>
    );
  }
}

15. Refs 和 DOM

15.1 什么是 Refs?

Refs 提供了一种访问 DOM 节点或 React 元素的方式。

class MyComponent extends React.Component {
  constructor(props) {
    super(props);
    this.myRef = React.createRef();
  }
  render() {
    return <div ref={this.myRef} />;
  }
}

16. useState 和 useEffect

16.1 useState

useState 是一个 Hook,用于在函数组件中添加状态。

function Example() {
  const [count, setCount] = useState(0);

  return (
    <div>
      <p>You clicked {count} times</p>
      <button onClick={() => setCount(count + 1)}>
        Click me
      </button>
    </div>
  );
}

16.2 useEffect

useEffect 是一个 Hook,用于在函数组件中执行副作用操作。

function Example() {
  const [count, setCount] = useState(0);

  useEffect(() => {
    document.title = `You clicked ${count} times`;
  });

  return (
    <div>
      <p>You clicked {count} times</p>
      <button onClick={() => setCount(count + 1)}>
        Click me
      </button>
    </div>
  );
}

17. useContext

17.1 使用 useContext

useContext 是一个 Hook,用于在函数组件中使用 Context API。

const ThemeContext = React.createContext('light');

function App() {
  return (
    <ThemeContext.Provider value="dark">
      <Toolbar />
    </ThemeContext.Provider>
  );
}

function Toolbar() {
  const theme = useContext(ThemeContext);
  return (
    <div>
      <ThemedButton />
    </div>
  );
}

18. useReducer

18.1 使用 useReducer

useReducer 是一个 Hook,用于在函数组件中管理复杂的状态逻辑。

const initialState = {count: 0};

function reducer(state, action) {
  switch (action.type) {
    case 'increment':
      return {count: state.count + 1};
    case 'decrement':
      return {count: state.count - 1};
    default:
      throw new Error();
  }
}

function Counter() {
  const [state, dispatch] = useReducer(reducer, initialState);
  return (
    <>
      Count: {state.count}
      <button onClick={() => dispatch({type: 'decrement'})}>-</button>
      <button onClick={() => dispatch({type: 'increment'})}>+</button>
    </>
  );
}

19. 自定义 Hooks

19.1 创建自定义 Hook

自定义 Hook 是一个函数,名称以 use 开头,可以在其中使用其他 Hooks。

function useFriendStatus(friendID) {
  const [isOnline, setIsOnline] = useState(null);

  useEffect(() => {
    function handleStatusChange(status) {
      setIsOnline(status.isOnline);
    }

    ChatAPI.subscribeToFriendStatus(friendID, handleStatusChange);
    return () => {
      ChatAPI.unsubscribeFromFriendStatus(friendID, handleStatusChange);
    };
  });

  return isOnline;
}

20. Hooks 规则和最佳实践

20.1 规则

  • 只在顶层调用 Hooks。
  • 只在 React 函数组件和自定义 Hooks 中调用 Hooks。

20.2 最佳实践

  • 使用 useEffect 来管理副作用。
  • 使用 useContext 来共享全局状态。

21. Redux 基础

21.1 什么是 Redux?

Redux 是一个用于管理应用状态的 JavaScript 库。

21.2 核心概念

  • Store:存储应用状态的对象。
  • Action:描述状态变化的简单对象。
  • Reducer:纯函数,根据 Action 更新 Store。
const store = createStore(reducer);

store.dispatch({ type: 'INCREMENT' });

22. Redux Toolkit

22.1 使用 Redux Toolkit

Redux Toolkit 是 Redux 的官方工具集,简化了 Redux 的使用。

import { createSlice, configureStore } from '@reduxjs/toolkit';

const counterSlice = createSlice({
  name: 'counter',
  initialState: 0,
  reducers: {
    increment: state => state + 1,
    decrement: state => state - 1
  }
});

const store = configureStore({
  reducer: counterSlice.reducer
});

23. MobX 简介

23.1 什么是 MobX?

MobX 是一个简单、可扩展的状态管理库。

23.2 核心概念

  • Observable:可观察的状态。
  • Action:改变状态的操作。
  • Reaction:自动响应状态变化的副作用。
import { observable, action, makeObservable } from 'mobx';

class Counter {
  count = 0;

  constructor() {
    makeObservable(this, {
      count: observable,
      increment: action,
      decrement: action
    });
  }

  increment() {
    this.count++;
  }

  decrement() {
    this.count--;
  }
}

24. Recoil 入门

24.1 什么是 Recoil?

Recoil 是一个用于 React 的状态管理库,由 Facebook 开发。

24.2 核心概念

  • Atom:存储状态的基本单位。
  • Selector:派生状态的纯函数。
import { atom, selector, useRecoilState, useRecoilValue } from 'recoil';

const counterState = atom({
  key: 'counterState',
  default: 0
});

const doubleCountState = selector({
  key: 'doubleCountState',
  get: ({get}) => get(counterState) * 2
});

25. 状态管理最佳实践

25.1 选择合适的状态管理工具

  • 对于小型应用,可以使用 React 的 useState 和 useReducer。
  • 对于大型应用,可以考虑使用 Redux、MobX 或 Recoil。

25.2 保持状态的单一来源

确保应用的状态只有一个来源,避免状态分散在多个组件中。

26. React Router 基础

26.1 安装 React Router

npm install react-router-dom

26.2 基本用法

import { BrowserRouter as Router, Route, Switch } from 'react-router-dom';

function App() {
  return (
    <Router>
      <Switch>
        <Route path="/about">
          <About />
        </Route>
        <Route path="/users">
          <Users />
        </Route>
        <Route path="/">
          <Home />
        </Route>
      </Switch>
    </Router>
  );
}

27. 动态路由

27.1 动态路由参数

你可以使用 : 来定义动态路由参数。

<Route path="/users/:id">
  <User />
</Route>

27.2 获取路由参数

使用 useParams Hook 获取路由参数。

import { useParams } from 'react-router-dom';

function User() {
  let { id } = useParams();
  return <h1>User: {id}</h1>;
}

28. 嵌套路由

28.1 嵌套路由

你可以在组件中嵌套 Route 组件来实现嵌套路由。